"""
ChatPromptTemplate

实例化的方式（使用构造方法、from_messages()）

调用提示词模板的方法 invoke()  format()  format_message() format_prompt()

更丰富的实例化参数类型

结合LLM

插入消息列表 MessagesPlaceholder
"""
import os

import dotenv
from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, \
    MessagesPlaceholder
from langchain_openai import ChatOpenAI


#使用构造方法创建实例
def fun_1():
    chat_prompt_template = ChatPromptTemplate(
        messages=[("system" , "你是一个AI助手，你的名字叫{name}") , ("human" , "我的问题是{question}")]
        ,input_variables=["name" , "question"]
    )
    prompt = chat_prompt_template.invoke(input={"name": "百事通" , "question": "你叫什么名字？"}) # invoke()返回的是 ChatPromptValue类型
    print(prompt)

#fun_1()

#使用 from_messages() 创建实例
def fun_2():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system" , "你是一个AI助手，你的名字叫{name}")
        , ("human" , "{question}")
    ])
    prompt = chat_prompt_template.invoke(input={"name": "百事通", "question": "你叫什么名字？"})
    print(prompt)

#fun_2()

#使用 format()
def fun_3():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , ("human", "{question}")
    ])
    prompt = chat_prompt_template.format(name="百事通", question="你叫什么名字？")
    print(prompt)

#fun_3()

#使用 format_messages()
def fun_4():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , ("human", "{question}")
    ])
    prompt = chat_prompt_template.format_messages(name="百事通", question="你叫什么名字？") # 返回的是 format_messages() 返回的是一个列表
    print(prompt)

#fun_4()

#使用 format_prompt()
def fun_5():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , ("human", "{question}")
    ])
    prompt = chat_prompt_template.format_prompt(name="百事通", question="你叫什么名字？") # 输出的是 format_prompt() 返回的 ChatPromptValue,与invoke()方法一样。只是传入的参数方式不同
    print(prompt)
    print(prompt.to_string()) # 返回的结果与format()方法一样
    print(prompt.to_messages()) # 返回的结果与format_messages()方法一样，是一个消息构成的列表

#fun_5()

"""
了解：
无论采用哪种创建实例的方式，messages参数的类型是列表。但是列表里的元素类型可以使字符串类型、字典类型、元祖、BaseMessage类型、ChatPromptTemplate类型、MessagePromptTemplate类型
"""

#使用字符串
def fun_6():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        "我的问题是{question}" #默认就是human消息
    ])
    prompt = chat_prompt_template.format_prompt(question="你叫什么名字？")
    print(prompt)

#字典类型
def fun_7():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        {"role": "system" , "content": "你是一个AI助手，你的名字叫{name}"},{"role": "human" , "content": "我的问题是{question}"}
    ])
    prompt = prompt = chat_prompt_template.format_prompt(name="百事通", question="你叫什么名字？")
    print(prompt)

# fun_6()
# fun_7()

#BaseMessage类型
def fun_8():
    from langchain_core.messages import SystemMessage
    chat_prompt_template = ChatPromptTemplate.from_messages([
        SystemMessage(content="你是一个AI助手，你的名字叫{name}")
        ,HumanMessage(content="我的问题是{question}")
    ])
    prompt = prompt = chat_prompt_template.format_prompt(name="百事通", question="你叫什么名字？")
    print(prompt)

#fun_8()

#ChatPromptTemplate类型
def fun_9():
    from langchain.prompts import ChatPromptTemplate
    chat_prompt_template_1 = ChatPromptTemplate.from_messages([("system" , "你是一个AI助手，你的名字叫{name}")])
    chat_prompt_template_2 = ChatPromptTemplate.from_messages([("human" , "我的问题是{question}")])

    chat_prompt_template = ChatPromptTemplate.from_messages([chat_prompt_template_1 , chat_prompt_template_2])
    prompt = chat_prompt_template.format_prompt(name="百事通", question="你叫什么名字？")
    print(prompt)

#fun_9()

#MessagePromptTemplate类型
def fun_10():
    # 创建系统提示
    system_template = "你从事的专业是{role}"
    system_message_prompt = SystemMessagePromptTemplate.from_template(system_template)

    human_template = "给我介绍下{concept}"
    human_message_prompt = HumanMessagePromptTemplate.from_template(human_template)

    # 消息组合
    chat_prompt = ChatPromptTemplate.from_messages([system_message_prompt, human_message_prompt])

    #格式化提示词
    formatted_messages = chat_prompt.format_messages(role="程序员", concept="JAVA")
    print(formatted_messages)

#fun_10()

#结合LLM
def fun_11():
    dotenv.load_dotenv()

    # 调用会话模型，这里使用阿里百炼平台里的千问3
    chat_model = ChatOpenAI(
        model=os.getenv("MODEL_NAME")
        , base_url=os.getenv("BASE_URL")
        , api_key=os.getenv("API_KEY")
        , temperature=0.8  # 精确度
        , max_tokens=1024  # 回答长度
        , streaming=True  # 是否流式返回
    )

    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , ("human", "{question}")
    ])
    prompt = chat_prompt_template.invoke(input={"name": "百事通", "question": "介绍下JAVA"})

    for chunk in chat_model.stream(prompt.to_string()):
        print(chunk.content, end="", flush=True)  # 输出流式数据 , end=""的作用是输出不换行 , flush=True作用是输出立即刷新

#fun_11()

#插入消息列表 MessagesPlaceholder
def fun_12():
    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , MessagesPlaceholder(variable_name="msgs")
    ])
    prompt = chat_prompt_template.invoke(input={
        "name": "百事通"
        , "msgs": [HumanMessage(content="介绍下JAVA")]
    })
    print(prompt)

#fun_12()

#MessagesPlaceholder 可以用于存储历史对话记录
def fun_13():
    dotenv.load_dotenv()

    # 调用会话模型，这里使用阿里百炼平台里的千问3
    chat_model = ChatOpenAI(
        model=os.getenv("MODEL_NAME")
        , base_url=os.getenv("BASE_URL")
        , api_key=os.getenv("API_KEY")
        , temperature=0.8  # 精确度
    )

    chat_prompt_template = ChatPromptTemplate.from_messages([
        ("system", "你是一个AI助手，你的名字叫{name}")
        , MessagesPlaceholder(variable_name="history")
        , ("human", "{question}")
    ])

    prompt = chat_prompt_template.invoke(input={
        "history": [HumanMessage(content="介绍下PYTHON") , AIMessage(content="PYTHON非常容易")]
        ,"name": "百事通"
        ,"question": "我刚才问了啥？"
    })
    #prompt = chat_prompt_template.format_messages(history=[HumanMessage(content="介绍下PYTHON")], name="百事通", question="我刚才问了啥？")
    response = chat_model.invoke(prompt)
    print(response.content)

#fun_13()